import character
from utils import Directions, RenderRepr, expand_tuple_keys
import tiles

movement_keys = {
    "up": Directions.north,
    "right": Directions.east,
    "down": Directions.south,
    "left": Directions.west,

    "kp_7": Directions.northwest,
    "kp_8": Directions.north,
    "kp_9": Directions.northeast,
    "kp_4": Directions.west,
    "kp_6": Directions.east,
    "kp_1": Directions.southwest,
    "kp_2": Directions.south,
    "kp_3": Directions.southeast,

    "7": Directions.northwest,  # Non-keypad number movement may be temporary
    "8": Directions.north,
    "9": Directions.northeast,
    "4": Directions.west,
    "6": Directions.east,
    "1": Directions.southwest,
    "2": Directions.south,
    "3": Directions.southeast
}


class Player(character.Character):
    def __init__(self):
        super().__init__()
        self.properties["walk_speed"] = 100
        self.render_repr = RenderRepr("@", (200, 200, 100), None)

    def place_on_map(self, target_tile):
        super().place_on_map(target_tile)
        self.game.add_task(0, self.turn)

    def walk_direction(self, direction):
        success = super().walk_direction(direction)
        if success:
            self.tile.level.los_changed = True
        return success

    def key_movement(self, key):
        if self.walk_direction(movement_keys[key.char]):
            return self.walk_speed

    def key_push(self, key):
        dir_key = self.game.get_next_key()
        if dir_key.char in movement_keys:
            direction = movement_keys[dir_key.char]
            obj = self.tile.around_tiles[direction]["wall"].obj
            if isinstance(obj, tiles.Boulder):
                obj.push(direction)
                return self.walk_speed * 2

    def key_wait(self, key):
        return 25

    def key_crush(self, key):
        dir_key = self.game.get_next_key()
        if dir_key.char in movement_keys:
            direction = movement_keys[dir_key.char]
            target_tile = self.tile.around_tiles[direction]
            obj = target_tile["wall"].obj
            if obj is not None:
                rubble = tiles.Rubble(obj)
                obj.remove_from_map()
                rubble.place_on_map(target_tile)
                return self.walk_speed * 2

    def key_pick_up(self, key):
        item = self.tile["items"].get_some()
        if item is not None:
            self.pick_up(item)

    def turn(self):
        key_binds = expand_tuple_keys({
            tuple(movement_keys.keys()): self.key_movement,
            "c": self.key_crush,
            "p": self.key_push,
            ".": self.key_wait,
            ",": self.key_pick_up
        })
        if not self.tile:
            return
        key = self.game.player_turn()
        if key is None:
            self.game.restart_task(self.turn)
            return
        if key in key_binds:
            function = key_binds[key]
        elif key.char in key_binds:
            function = key_binds[key.char]
        else:
            self.game.restart_task(self.turn)
            return
        delay = function(key)
        if delay is None:
            self.game.restart_task(self.turn)
        else:
            self.game.add_task(delay, self.turn)
